package lookup;

import domain.User;
import org.junit.Test;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

/**
 * ObjectProvider Bean 的延迟查找
 * @author jackcfan
 * @date 2021/9/13
 */
@Configuration
public class ObjectProviderTest {
    @Test
    public void test(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.register(this.getClass());
        applicationContext.refresh();

        // 1. Bean 的延迟查找,调用 getObject() 时才查找
        ObjectProvider<String> stringProvider = applicationContext.getBeanProvider(String.class);
        System.out.println("getObject -> "+stringProvider.getObject());

        // 2. getObject 获取 Bean，不存在则抛出异常
        ObjectProvider<User> userProvider = applicationContext.getBeanProvider(User.class);
        try{
            User user = userProvider.getObject();
        }catch (Exception e){
            System.out.println("Exception : user Bean 不存在！！！"+e.getMessage());
        }

        // 3. getIfAvailable 安全的获取 Bean ，不会抛出异常，返回 null
        User userNotExists = userProvider.getIfAvailable();
        System.out.println("用户Bean不存在 ? "+(userNotExists == null));

        // 4. getIfAvailable 如果找不到 Bean 对象，则返回 User::createUser 创建的对象
        // 避免返回空对象
        User user = userProvider.getIfAvailable(()->User.createUser());
        System.out.println("userProvider:"+user);

        // for遍历，ObjectProvider 实现了 Iterable 接口，可以直接遍历
        Iterable<String> stringIterable = stringProvider;
        for(String obj : stringIterable){
            System.out.println("foreach:"+obj);
        }

        // 使用 stream 遍历
        System.out.println("使用 stream 遍历");
        stringProvider.stream().forEach(System.out::println);

        applicationContext.close();
    }

    /**
     * 默认方法名就是 Bean 名称
     */
    @Bean
    @Primary
    public String helloWorld(){
        System.out.println("string bean init...");
        return "hello,world";
    }

    @Bean
    public String message(){
        System.out.println("message bean init...");
        return "message string";
    }
}
